package com.gather.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.common.constant.SnatchConstant;
import com.common.dto.LoginAccount;
import com.common.dto.WebInfo;
import com.common.dto.WebNode;
import com.common.dto.WebUrl;
import com.common.system.SystemData;
import com.gather.service.AccountService;
import com.gather.service.LoggerService;
import com.gather.system.AccountData;
import com.work.service.SnatchControl;
import com.work.service.SnatchService;
import com.work.vo.LoginData;
import com.work.vo.ThirdInfo;

@Service
public class AccountServiceImpl implements AccountService{
	
	ConcurrentMap<String, Login> loginThreds = new ConcurrentHashMap<String, Login>();// 每个登录线程的名字和线程ID
	
	protected Logger log = Logger.getLogger(AccountServiceImpl.class);
	
	
	SnatchService hgSnatchDataImpl;
	
	@Autowired
	LoggerService loggerService;
	
	long sleepTiem = 35*1000;
	
	@Override
	public int loginAccount(String webCode) {
		if(null != webCode){
			if(!loginThreds.containsKey(webCode)){
				Login login = new Login(webCode);
				new Thread(login).start();
				loginThreds.put(webCode, login);
			}
		}
		return SnatchConstant.SUCCESS;
	}
	

	
	private List<LoginData> foundLoginData(WebNode webConfig){
		String webCode = webConfig.getWebCode();
		List<LoginData> list = new ArrayList<LoginData>();
		for(LoginAccount loginAccount : webConfig.getLoginAccounts()){
			if(!haveData(webCode,loginAccount.getUserName())){
				LoginData loginData = new LoginData();
				loginData.setLogin(false);
				loginData.setOnlyCode(webCode);
				/**
				 * 代理 url 权重
				 */
				if(webConfig.getProxys().size()>0){
					if(webConfig.getProxys().size()==1){
						loginData.setProxy(webConfig.getProxys().get(0));
					}else{
						loginData.setProxy(webConfig.getProxys().get(new Random().nextInt(webConfig.getProxys().size()-1)));
					}
				}
				WebInfo webInfo = new WebInfo();
				/**
				 * 设置url权重
				 */
				WebUrl webUrl = null;
				if(webConfig.getWebUrls().size()==1){
					webUrl = webConfig.getWebUrls().get(0);
				}else{
					webUrl = webConfig.getWebUrls().get(new Random().nextInt(webConfig.getWebUrls().size()-1));
				}
				webInfo.setUrl(webUrl.getUrl());
				webInfo.setSnatchWeb(webConfig.getWebCode());
				webInfo.setReadTimeOut(webConfig.getReadTimeOut());
				webInfo.setConnectionTimeOut(webConfig.getConnectionTimeOut());
				webInfo.setLangx(webConfig.getLangx());
				loginData.setWebConfig(webInfo);
				loginData.setLoginAccount(loginAccount);
				list.add(loginData);
			}
		}
		return list;
	}
	
	/**
	 * 不存在数据
	 * @param web
	 * @param username
	 * @return
	 */
	private boolean haveData(String webCode,String username){
		CopyOnWriteArrayList<ThirdInfo> list = AccountData.thirdInfos.get(webCode);
		if(null == list){
			return false;
		}
		for(ThirdInfo thirdInfo : list){
			if(thirdInfo.getLoginAccount().getUserName().equals(username)){
				return true;
			}
		}
		return false;
	}
	
	
	private class Login implements Runnable{
		
		private String webCode;
		private boolean flag = true;	//控制变量
		
		public Login(String webCode){
			this.webCode = webCode;
		}
		
		private List<LoginData> findLoginData(WebNode webNode){
			List<LoginData> list = foundLoginData(webNode);
			return list;
		}
		public void destroyLoginThread(){
			flag = false;
		}
		@Override
		public void run() {
			while (flag) {
				try {
					WebNode webNode = SystemData.findWebNode(webCode);
					if(webNode != null) {
						hgSnatchDataImpl = SnatchControl.getSnatchService(webCode);
						List<LoginData> list = findLoginData(webNode);
							for(LoginData loginData : list){
								String userName = loginData.getLoginAccount().getUserName();
								//帐号未登录并且是有效的
								if(!loginData.getLoginAccount().isLogin() && loginData.getLoginAccount().isValid()){
									if(loginData.getLoginAccount().getTryNum()<4){
										ThirdInfo thirdInfo ;
										
										addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+" 开始登录！");
										try {
											thirdInfo = (ThirdInfo) hgSnatchDataImpl.connectionWeb(loginData);
											loginData.getLoginAccount().addTryNum();
											if(null == thirdInfo){
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+SnatchConstant.ERROR_NOT_OBJECT);
												continue;
											}
											boolean refreshRet = hgSnatchDataImpl.refreshValidateCode(thirdInfo);
											int tryNum = 1;
											while (!refreshRet && tryNum<5 ) {
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+"刷新验证码失败,重试... " + tryNum);
												refreshRet = hgSnatchDataImpl.refreshValidateCode(thirdInfo);
												tryNum++;
											}
											int loginStatus = hgSnatchDataImpl.login(thirdInfo);// 登录
											if (loginStatus == SnatchConstant.SUCCESS) {// 登录成功
												AccountData.addThirdInfo(webCode,thirdInfo);
												loggerService.addNodeLoginLog(webCode, "");
												loginData.getLoginAccount().setTryNum(0);
												loginData.getLoginAccount().setLogin(true);
												loginData.getLoginAccount().setValid(true);
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+" 登录成功!");
												
											}  else if (loginStatus == SnatchConstant.LOGIN_FAIL_WRONG_USERNAME_OR_PASSWORD) {// 用户名或密码错误
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+" 登录失败,用户名【" + userName + "】或密码【" +  loginData.getLoginAccount().getUserPwd() + "】错误!");
												loginData.getLoginAccount().setValid(false);
											} else if (loginStatus == SnatchConstant.LOGIN_FAIL_SYSTEM_MAINTENANCE) {// 系统维护
												String message = "标识ID："+loginData.getWebConfig().getSnatchWeb()+" 帐号："+loginData.getLoginAccount().getUserName()+ "登录失败,系统正在维护中......";
												addLogger(webCode, userName, message);
												loginData.getLoginAccount().setTryNum(0);
												loggerService.addNodeThirdLog(webCode, message);
												break;
											} else if (loginStatus == SnatchConstant.LOGIN_FAIL_CHANGE_PASSWORD) {// 变更密码
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+ "【" + userName + "】登录失败,该密码【" + loginData.getLoginAccount().getUserPwd()
														+ "】久未变更,为了安全起见,请先变更密码后再继续使用!");
												loginData.getLoginAccount().setValid(false);
											} else if (SnatchConstant.LOGIN_FAIL_ACCOUNT_LOCKED == loginStatus) {
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+ "登录时,帐号已关闭");
												loginData.getLoginAccount().setValid(false);
											} else if (SnatchConstant.LOGIN_FAIL_WRONG_VC == loginStatus) {
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+ "登录时验证码错误");
											} else {
												addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+ "登录失败,错误码："+loginStatus);
											}
											
										} catch (Exception e) {
											e.printStackTrace();
											loggerService.addAccountLog(webCode,userName,"标识ID："+webCode+" 帐号："+userName+" 登录时报错");
											log.error("标识ID："+webCode+" 帐号："+userName+" 登录时报错");
										}
									}else{
										addLogger(webCode, userName, "标识ID："+webCode+" 帐号："+userName+ "尝试次数太多!");
									}
							}
							
						}
					}
					
					Thread.sleep(sleepTiem);
				} catch (Exception e) {
					loggerService.addNodeLoginLog(webCode, "登录时报错："+e.getMessage());
					log.error(e);
				}
			}
				
		}
		
	}



	private void addLogger(String webCode,String userName,String message){
		loggerService.addAccountLog(webCode,userName,message);
		log.info(message);
	}







}
